package vben.core.common.mvc.service;

import cn.hutool.core.util.StrUtil;
import vben.core.common.mvc.api.PageData;
import vben.core.common.mvc.dao.JdbcDao;
import vben.core.common.mvc.dao.Sqler;
import vben.core.common.mvc.entity.BaseCateEntity;
import vben.core.common.mvc.pojo.ZidName;
import vben.core.common.utils.lang.IdUtils;
import vben.core.common.mvc.pojo.Ztree;
import vben.core.common.utils.web.XuserUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

//分类Service基类，提供分类Entity增删改查的通用方法
@Transactional(rollbackFor = Exception.class)
public abstract class BaseCateService<T extends BaseCateEntity> {

    //---------------------------------------查询-------------------------------------
    //查询Tree树形集合数据
    public List<Ztree> findTreeList(String table, String name) {
        Sqler sqler = new Sqler(table);
        sqler.addSelect("t.pid");
        sqler.addLike("t.name", name);
        sqler.addOrder("t.ornum");
        List<Ztree> list = jdbcDao.findTreeList(sqler);
        return list;
    }

    //查询分页
    @Transactional(readOnly = true)
    public PageData findPageData(Sqler sqler) {
        sqler.selectCUinfo().addSelect("t.label");
        sqler.addOrder("t.ornum");
        return jdbcDao.findPageData(sqler);
    }

    //查询ZidName集合
    @Transactional(readOnly = true)
    public List<ZidName> findIdNameRes(Sqler sqler) {
        return jdbcDao.findIdNameList(sqler);
    }


    //用户编辑时选择父类别，不能选择自己及孩子节点，否则会造成无限循环
//    @Transactional(readOnly = true)
//    public List<Ztree> inpChoose(String table, String id, String name){
//        Sqler sqler = new Sqler(table);
//        sqler.addSelect("pid");
//        sqler.addWhere("t.avtag = 1");
//        if (StrUtil.isNotBlank(id)) {
//            sqler.addWhere("t.tier not like ?", "%;" + id + ";%");
//            sqler.addWhere("t.id <> ?", id);
//        }
//        if(StrUtil.isNotBlank(name)){
//            sqler.addLike("t.name", name);
//        }
//        sqler.addOrder("t.ornum");
//        return jdbcDao.findInpList(sqler);
//    }

    //查询ZidName集合
    @Transactional(readOnly = true)
    public List<Ztree> tier2Choose(String table, String id, String name){
        Sqler sqler = new Sqler(table);
        sqler.addSelect("pid");
        sqler.addWhere("t.avtag = 1");
        if (StrUtil.isNotBlank(id)) {
            sqler.addWhere("t.tier not like ?", "%x" + id + "x%");
            sqler.addWhere("t.id <> ?", id);
        }
        if(StrUtil.isNotBlank(name)){
            sqler.addLike("t.name", name);
        }
        sqler.addOrder("t.ornum");
        return jdbcDao.findTreeList(sqler);
    }

//    @Transactional(readOnly = true)
//    public R inpFind(String table){
//        Sqler sqlHelper = new Sqler(table);
//        sqlHelper.addSelect("pid");
//        sqlHelper.addWhere("t.avtag = 1");
//        sqlHelper.addOrder("t.ornum");
//        return R.ok(jdbcDao.findInpList(sqlHelper));
//    }
//
//    public R inpDele(String table, String id){
//        String sql = "select id from " + table + " where tier like ? order by tier";
//        List<String> stringList = jdbcDao.findStringList(sql, "%;" + id + ";%");
//        for (String sid : stringList) {
//            repo.deleteById(sid);
//        }
//        repo.deleteById(id);
//        return R.ok();
//    }

    //查询单个实体详细信息
    @Transactional(readOnly = true)
    public T findOne(String id) {
        return repo.findById(id).get();
    }

    //---------------------------------------增删改-------------------------------------
    //新增
    public String insert(T cate) {
        if(cate.getId()==null||"".equals(cate.getId())){
            cate.setId(IdUtils.getUID());
        }
        if(cate.getCrman()==null){
            cate.setCrman(XuserUtil.getUser());
        }
        if (cate.getParent() != null) {
            T parent = repo.findById(cate.getParent().getId()).get();
            cate.setTier(parent.getTier()+cate.getId()+ "x");
        } else {
            cate.setTier("x"+cate.getId()+"x");
        }
//        cate.setCrtim(new Date());
        cate.setUptim(cate.getCrtim());
        repo.save(cate);
        return cate.getId();
    }

    //更新
    public String update(T cate){
        cate.setUptim(new Date());
        if(cate.getUpman()==null){
            cate.setUpman(XuserUtil.getUser());
        }
        repo.save(cate);
        return cate.getId();
    }

    //级联更新
    public String update(T cate,String table,boolean tierChange){
        cate.setUptim(new Date());
        if(cate.getUpman()==null){
            cate.setUpman(XuserUtil.getUser());
        }
        String newPid = "";
        if(cate.getParent()!=null){
            newPid=cate.getParent().getId();
        }
        T oldCate=repo.findById(cate.getId()).get();
        String oldPid="";
        if(oldCate.getParent()!=null){
            oldPid  =oldCate.getParent().getId();
        }
        String oldTier=oldCate.getTier();
        if(oldPid.equals(newPid)&&!tierChange){//如果父节点没有变，则只更新自己
//            System.out.println("父节点没有变");
            cate.setTier(oldTier);
            repo.save(cate);
        }else{//如果父节点变了，则另外需要更新自己孩子节点的tier层级
            String newTier = "x"+cate.getId()+"x";
            if(cate.getParent()!=null){
//                System.out.println("父节点变成其他点了");
                T newParentCate=repo.findById(cate.getParent().getId()).get();
                newTier =newParentCate.getTier()+cate.getId()+"x";
            }
            cate.setTier(newTier);
            repo.save(cate);
            //更新子节点
            String sql = "select id,tier as name from " + table + " where tier like ? and id<>?";
//            System.out.println(sql);
            List<ZidName> list = jdbcDao.findIdNameList(sql, oldTier+"%",cate.getId());

            String updateSql = "update " + table + " set tier=? where id=?";
            List<Object[]> updateList = new ArrayList<Object[]>();
            for (ZidName ztwo : list) {
                Object[] arr = new Object[2];
                arr[0] = ztwo.getName().replace(oldTier,newTier);
                arr[1] = ztwo.getId();
                updateList.add(arr);
            }
            jdbcDao.batch(updateSql, updateList);
        }
        return cate.getId();
    }

    //删除
    public int delete(String[] ids) {
        for (String id : ids) {
            repo.deleteById(id);
        }
        return ids.length;
    }

    //---------------------------------------构建树形结构辅助方法-------------------------------------
    //使用递归方法建树
    public List<T> buildByRecursive(List<T> nodes) {
        List<T> list = new ArrayList<>();
        for (T node : nodes) {
            if (node.getPid() == null) {
                list.add(findChildrenByTier(node, nodes));
            } else {
                boolean flag = false;
                for (BaseCateEntity node2 : nodes) {
                    if (node.getPid().equals(node2.getId())) {
                        flag = true;
                        break;
                    }
                }
                if (!flag) {
                    list.add(findChildrenByTier(node, nodes));
                }
            }
        }
        return list;
    }

    //递归查找子节点
    private T findChildrenByTier(T node, List<T> nodes) {
        for (T item : nodes) {
            if (node.getId().equals(item.getPid())) {
                if (node.getChildren() == null) {
                    node.setChildren(new ArrayList<>());
                }
                node.getChildren().add(findChildrenByTier(item, nodes));
            }
        }
        return node;
    }

    //---------------------------------------bean注入-------------------------------------

    @Autowired
    protected JdbcDao jdbcDao;

    protected JpaRepository<T,String> repo;

    public void setRepo(JpaRepository<T,String> repo) {
        this.repo = repo;
    }
}